/**
 * 处理关于 checkbox 或者 radio 的控件
 */

layui.define(['jquery', 'form'], function(exports) {
  var $ = layui.jquery;
  var form = layui.form;

  var MODULE_NAME = 'choose';
  var FIELD   = 'data-field';
  var CHOOSE  = 'data-choose';

  var Choose = function() {
    this.v = '1.0.1';
  };

  $.extend(Choose.prototype, {
    /**
     * 设置单复选框的值
     * @param {Object} option
     * @param {Object|Function} callbacks {success:fn, error: fn, complete: fn} | fn
     */
    set: function(option, callbacks) {
      var config = {
        el       : null, // {string|HTMLElement} 选填，jQuery 选择器，用于指定一个 dom 范围，默认是整个文档
        name     : null, // {string} 必填，单复选框上的字段名
        type     : 'checkbox', // {string} 选填，值是 checkbox / radio，默认是 checkbox
        labelKey : 'text', // {string} 选填，返回值的关键字，默认是 text
        valueKey : 'id', // {string} 选填，返回值的关键字，默认是 id
        selectKey: 'selected', // {string} 选填，返回值的关键字，默认是 selected
        $data    : null, // {Array} 选填，不使用 jQuery.ajax 获取值，直接使用数据拼接，与 url 二选一，优先级高于 url
        // $.ajax
        url      : null, // {string} 选填，jQuery.ajax 中的 url 参数，与 $data 二选一，优先级低于 $data
        method   : 'POST', // {string} 选填，jQuery.ajax 中的 type 参数，默认 post
        data     : {} // {Object} 选填，jQuery.ajax 中的 data 参数
      };

      var typeOption = $.type(option);
      if (typeOption !== 'object') return;

      $.extend(config, option); // 合并参数

      var $scope = config.el ? $(config.el) : $('[name="' + config.name + '"]');
      if (!$scope.length) return;

      $scope = $scope.first(); // 首次只对匹配项做处理

      // 2018/10/24 为当前的容器配置属性
      $scope.attr(CHOOSE, config.type).attr(FIELD, config.name);

      // 2018/10/25 关于 data 可以传入一个唯一的 object
      var renderTemplate = function(data) {
        var raw = []; var nodeText = '';

        var typeData = $.type(data);
        if (typeData === 'object') {
          raw.push(data);
        } else if (typeData === 'array') {
          raw = data;
        }

        $.each(raw, function(_, item) {
          nodeText += '<input name="' + config.name + '" value="' + item[config.valueKey] + '" type="' + config.type + '" lay-skin="primary" title="' + item[config.labelKey] + '"' + (item[config.selectKey] ? ' checked' : '') + '>';
        });

        $scope.html(nodeText);
        form.render(config.type);
      };

      // 2019/05/15 当渲染完毕调用回调函数
      var typeCallbacks = $.type(callbacks);
      var successFn, errorFn, completeFn;
      if (typeCallbacks === 'function') {
        completeFn = callbacks;
      } else if (typeCallbacks === 'object') {
        successFn = callbacks.success;
        errorFn = callbacks.error;
        completeFn = callbacks.complete;
      }

      if (config.$data) {
        var type$data = $.type(config.$data);
        if (type$data === 'string') {
          try {
            config.$data = JSON.parse(config.$data);
          } catch (e) {
            //
          }
        }

        renderTemplate(config.$data);
        $.isFunction(completeFn) && completeFn($scope);
      } else if (config.url) {
        $.ajax({
          url     : config.url,
          type    : config.method,
          data    : config.data,
          dataType: 'json',
          async   : true,
          cache   : false,
          success : function(response, status) {
            renderTemplate(response.data);
            $.isFunction(successFn) && successFn(response, status);
          },
          error: function(response, status) {
            $.isFunction(errorFn) && errorFn(response, status);
          },
          complete: function(response, status) {
            $.isFunction(completeFn) && completeFn(response, status);
          }
        });
      }
    },

    /**
     * 获取单复选框的值并以 ',' 隔开
     * @param {string|HTMLElement} el
     *  jQuery 选择器，用于指定一个 dom 范围，默认是整个文档
     * @param {string|Object} option
     *  配置选项，默认 { labelKey: 'name', valueKey: 'value', fieldKey: '' }
     *  如果是 string 则默认是 fieldKey 值
     */
    get: function(el, option) {
      var $scope = $(el);
      if (!$scope.length) return;

      var KEY_NAME = 'name'; var KEY_VALUE = 'value'; var KEY_FIELD = '';

      var typeOption = $.type(option);
      if (typeOption === 'string') {
        KEY_FIELD = option;
      } else if (typeOption === 'object') {
        KEY_NAME = option.labelKey || 'name';
        KEY_VALUE = option.valueKey || 'value';
      }

      var propField = $scope.attr(FIELD);
      var propChoose = $scope.attr(CHOOSE);
      propField = KEY_FIELD || propField.substring(propField.lastIndexOf('.') + 1, propField.length);
      propChoose = propChoose || 'checkbox';

      // 获取控件的标签名
      var getLabel = function($item) {
        var finalText = $item.attr('title') || $item.attr('label') || '';

        if (!finalText) {
          var $parent = $item.parent();
          var $label = $parent.find('label');
          var $span = $parent.find('span');

          if ($label.length === 1) {
            finalText = $parent.find('label').text();
          } else if ($span.length === 1) {
            finalText = $parent.find('span').text();
          }
        }

        return finalText;
      };
      // 注入结果
      var handleInject = function(label, value) {
        var ret = {}; var o = ret[propField] = {};
        o[KEY_NAME] = label;
        o[KEY_VALUE] = value;
        return ret;
      };
      // 复选框
      var getCheckboxValue = function() {
        var $target = $scope.find('input[type="checkbox"]:checked');
        var arrayLabel = []; var arrayValue = [];

        $target.each(function(_, item) {
          var $item = $(item);
          arrayLabel.push(getLabel($item));
          arrayValue.push($item.val());
        });

        return handleInject(arrayLabel.join(','), arrayValue.join(','));
      };
      // 单选框
      var getRadioValue = function() {
        var $target = $scope.find('input[type="radio"]:checked');
        return handleInject(getLabel($target), $target.val());
      };

      var isInput = $scope.is('input');

      if (isInput) {
        return handleInject(getLabel($scope), $scope.is(':checked') ? $scope.val() : '');
      } else {
        return propChoose === 'checkbox' ? getCheckboxValue() : (propChoose === 'radio' && getRadioValue());
      }
    }
  });

  exports(MODULE_NAME, new Choose());
});
